package serv_impl

import (
	"context"
	"encoding/json"

	"atomgit.com/openlinksaas/proto-gen-go.git/k8s_proxy_api"
	corev1 "k8s.io/api/core/v1"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)

func (apiImpl *K8SProxyApiImpl) getResourceUserPerm(ctx context.Context, nameSpace string, resourceType k8s_proxy_api.RESOURCE_TYPE, resourceName, userId string) *k8s_proxy_api.ResourceUserPerm {
	emptyPerm := &k8s_proxy_api.ResourceUserPerm{}
	k8sClientSet, err := getK8sClientSet(apiImpl.kubeConfigFile)
	if err != nil {
		return emptyPerm
	}
	client := k8sClientSet.CoreV1().ConfigMaps(nameSpace)
	res, err := client.Get(ctx, CONFIG_MAP_PERM, metav1.GetOptions{})
	if err != nil {
		return emptyPerm
	}
	key := ""
	if resourceType == k8s_proxy_api.RESOURCE_TYPE_RESOURCE_TYPE_DEPLOYMENT {
		key = CONFIG_MAP_DEPLOYMENT_PREFIX + resourceName
	} else if resourceType == k8s_proxy_api.RESOURCE_TYPE_RESOURCE_TYPE_STATEFULSET {
		key = CONFIG_MAP_STATEFULSET_PREFIX + resourceName
	}
	jsonStr, ok := res.Data[key]
	if !ok {
		return emptyPerm
	}
	perm := &k8s_proxy_api.ResourcePerm{}
	err = json.Unmarshal([]byte(jsonStr), perm)
	if err != nil {
		return emptyPerm
	}
	for _, userPerm := range perm.UserPermList {
		if userPerm.UserId == userId {
			return userPerm
		}
	}
	return emptyPerm
}

func (apiImpl *K8SProxyApiImpl) ListResourcePerm(ctx context.Context, req *k8s_proxy_api.ListResourcePermRequest) (*k8s_proxy_api.ListResourcePermResponse, error) {
	emptyList := []*k8s_proxy_api.ResourcePerm{}
	//检查权限
	tokenInfo, err := getTokenInfo(apiImpl.linkSaasAddr, req.Token)
	if err != nil {
		return nil, err
	}
	k8sClientSet, err := getK8sClientSet(apiImpl.kubeConfigFile)
	if err != nil {
		return nil, err
	}
	{
		if req.Namespace == "" {
			return &k8s_proxy_api.ListResourcePermResponse{
				Code:     k8s_proxy_api.ListResourcePermResponse_CODE_NO_PERMISSION,
				ErrMsg:   "必须指定命名空间",
				PermList: emptyList,
			}, nil
		}
		client := k8sClientSet.CoreV1().Namespaces()
		res, err := client.Get(ctx, req.Namespace, metav1.GetOptions{})
		if err != nil {
			return nil, err
		}
		if res.Labels[PROJECT_LABEL] != tokenInfo.ProjectId {
			return &k8s_proxy_api.ListResourcePermResponse{
				Code:     k8s_proxy_api.ListResourcePermResponse_CODE_NO_PERMISSION,
				ErrMsg:   "命名空间没有关联项目",
				PermList: emptyList,
			}, nil
		}
	}
	client := k8sClientSet.CoreV1().ConfigMaps(req.Namespace)
	res, err := client.Get(ctx, CONFIG_MAP_PERM, metav1.GetOptions{})
	if err != nil {
		return &k8s_proxy_api.ListResourcePermResponse{
			Code:     k8s_proxy_api.ListResourcePermResponse_CODE_OK,
			PermList: emptyList,
		}, nil
	}

	permList := []*k8s_proxy_api.ResourcePerm{}
	for _, name := range req.NameList {
		key := ""
		if req.ResourceType == k8s_proxy_api.RESOURCE_TYPE_RESOURCE_TYPE_DEPLOYMENT {
			key = CONFIG_MAP_DEPLOYMENT_PREFIX + name
		} else if req.ResourceType == k8s_proxy_api.RESOURCE_TYPE_RESOURCE_TYPE_STATEFULSET {
			key = CONFIG_MAP_STATEFULSET_PREFIX + name
		}
		jsonStr, ok := res.Data[key]
		if ok {
			perm := &k8s_proxy_api.ResourcePerm{}
			err = json.Unmarshal([]byte(jsonStr), perm)
			if err == nil {
				permList = append(permList, perm)
			}
		}
	}
	return &k8s_proxy_api.ListResourcePermResponse{
		Code:     k8s_proxy_api.ListResourcePermResponse_CODE_OK,
		PermList: permList,
	}, nil
}

func (apiImpl *K8SProxyApiImpl) SetResourcePerm(ctx context.Context, req *k8s_proxy_api.SetResourcePermRequest) (*k8s_proxy_api.SetResourcePermResponse, error) {
	//检查权限
	tokenInfo, err := getTokenInfo(apiImpl.linkSaasAddr, req.Token)
	if err != nil {
		return nil, err
	}
	if !tokenInfo.Admin {
		return &k8s_proxy_api.SetResourcePermResponse{
			Code:   k8s_proxy_api.SetResourcePermResponse_CODE_NO_PERMISSION,
			ErrMsg: "只有管理员可以设置权限",
		}, nil
	}
	k8sClientSet, err := getK8sClientSet(apiImpl.kubeConfigFile)
	if err != nil {
		return nil, err
	}
	{
		if req.Namespace == "" {
			return &k8s_proxy_api.SetResourcePermResponse{
				Code:   k8s_proxy_api.SetResourcePermResponse_CODE_NO_PERMISSION,
				ErrMsg: "必须指定命名空间",
			}, nil
		}
		client := k8sClientSet.CoreV1().Namespaces()
		res, err := client.Get(ctx, req.Namespace, metav1.GetOptions{})
		if err != nil {
			return nil, err
		}
		if res.Labels[PROJECT_LABEL] != tokenInfo.ProjectId {
			return &k8s_proxy_api.SetResourcePermResponse{
				Code:   k8s_proxy_api.SetResourcePermResponse_CODE_NO_PERMISSION,
				ErrMsg: "命名空间没有关联项目",
			}, nil
		}
	}
	client := k8sClientSet.CoreV1().ConfigMaps(req.Namespace)
	dataMap := map[string]string{}
	exist := false
	{
		res, err := client.Get(ctx, CONFIG_MAP_PERM, metav1.GetOptions{})
		if err == nil {
			dataMap = res.Data
			exist = true
		}
	}
	jsonData, err := json.Marshal(req.Perm)
	if err != nil {
		return nil, err
	}
	if req.Perm.ResourceType == k8s_proxy_api.RESOURCE_TYPE_RESOURCE_TYPE_DEPLOYMENT {
		dataMap[CONFIG_MAP_DEPLOYMENT_PREFIX+req.Perm.Name] = string(jsonData)
	} else if req.Perm.ResourceType == k8s_proxy_api.RESOURCE_TYPE_RESOURCE_TYPE_STATEFULSET {
		dataMap[CONFIG_MAP_STATEFULSET_PREFIX+req.Perm.Name] = string(jsonData)
	} else {
		return &k8s_proxy_api.SetResourcePermResponse{
			Code:   k8s_proxy_api.SetResourcePermResponse_CODE_NO_PERMISSION,
			ErrMsg: "只能设置deployment和statefulset权限",
		}, nil
	}
	if exist {
		_, err = client.Update(ctx, &corev1.ConfigMap{
			ObjectMeta: metav1.ObjectMeta{
				Name: CONFIG_MAP_PERM,
			},
			Data: dataMap,
		}, metav1.UpdateOptions{})
		if err != nil {
			return nil, err
		}
	} else {
		_, err = client.Create(ctx, &corev1.ConfigMap{
			ObjectMeta: metav1.ObjectMeta{
				Name: CONFIG_MAP_PERM,
			},
			Data: dataMap,
		}, metav1.CreateOptions{})
		if err != nil {
			return nil, err
		}
	}
	return &k8s_proxy_api.SetResourcePermResponse{
		Code: k8s_proxy_api.SetResourcePermResponse_CODE_OK,
	}, nil
}
